#ifndef frm_H
#define frm_H

#include "svl_TValue.h"
#include "svl_TPostMessage.h"
#include "grf_TDC.h"

namespace frm {

///////////////////////////////////////////////////////////////////////////////

struct TDebug
{
  TDebug() { objectsCount++;}
 ~TDebug() { objectsCount--;}
  //
  static void Check();

private:
  static int objectsCount;
  //
  struct TCheck
  {
   ~TCheck() { TDebug::Check();}
  };
  static TCheck check;
};

///////////////////////////////////////////////////////////////////////////////

//#define frm_Type(ParentClass) svl_Type(ParentClass)

/****************
#define frm_Type(ParentClass) \
  struct TType : public ParentClass::TType \
  { \
    TType() {} \
    virtual TComponent::TType &Type() { static TType T(&ParentClass::TType::Type()); return T;} \
  protected: \
    TType(TComponent::TType *Parent)  { parent = Parent;} \
  }; \
  virtual TComponent::TType &Type() { return TType().Type();}
********************/


///////////////////////////////////////////////////////////////////////////////
struct TComponentArray;
///////////////////////////////////////////////////////////////////////////////

struct TComponent : public TDebug , public svl::TArray_Object
{
/**************
  struct TType
  { 
    TType() {}
    //
    bool IsInternal(const TType &Class_);
    virtual TComponent::TType &Type() { static TType T(NULL); return T;} 
    
  protected:
    TType(TComponent::TType *Parent)  { parent = Parent;}
    TType *parent;
    friend TComponent;
  };
  virtual TComponent::TType &Type() { return TType().Type();}
  virtual char *ClassName() { return (char*)typeid(*this).name();}
****************/  
  svl_Type(svl::TArray_Object)
  //
  TComponent() { parent = NULL; }
 ~TComponent() { DeleteChildren(); }
  //
  virtual TComponent *GetParent() { return parent; }
  //
  virtual void AddChildFirst (TComponent *Add,bool EnDelete = true);
  virtual void AddChildLast  (TComponent *Add,bool EnDelete = true);
  virtual void AddChildBefore(TComponent *Add,TComponent *Curr,bool EnDelete = true);
  virtual void AddChildAfter (TComponent *Add,TComponent *Curr,bool EnDelete = true);
  //
  virtual void DeleteChildren();
  virtual void DeleteChild(int         N);
  virtual void DeleteChild(TComponent *Del) { DeleteChild(GetNChild(Del));}
  virtual void SwapChild(TComponent *Child1,TComponent *Child2);
  virtual void MoveChildrenTo(int ThisNFirstChild,int ThisNLastChild,int ToNBeforeChild,TComponent *ToParent);
  //virtual void MoveChildTo(int ThisNChild,TComponent *ToParent);
  //
  void PostDeleteChildren();
  void PostDeleteChild(TComponent *Del);
  void PostDeleteThis();
  //
  virtual int         GetChildrenCount()           { return children.Count(); }
  virtual int         GetNChild(TComponent *Child) { return children.GetN(Child); }
  virtual TComponent &GetChild(int N)              { return *dynamic_cast<TComponent*>(children.Get(N)); }
  virtual TComponent *GetFirstChild()              { return children.Count() > 0 ? &GetChild(0) : NULL; }
  virtual TComponent *GetLastChild()               { return children.Count() > 0 ? &GetChild(children.Count()-1) : NULL; }
  virtual bool        SearchChild(TComponent *P)   { return children.Search(P); }
  //
  void SetEnDeleteChild(int N,bool EnDelete) { children.SetEnDelete(N,EnDelete); }
  bool GetEnDeleteChild(int N)               { return children.GetEnDelete(N); }
  //
  void SetEnDeleteChild(TComponent *Child,bool EnDelete) { children.SetEnDelete(Child,EnDelete); }
  bool GetEnDeleteChild(TComponent *Child)               { return children.GetEnDelete(Child); }
  //
  void DeleteChildIfSearch(TComponent *P) { if (SearchChild(P)) { DeleteChild(P);} }
  //
  void DeleteThisFromParent()
  {
    TComponent *Parent = GetParent(); 
    if (Parent) {
      int N = Parent->GetNChild(this); 
      if (Parent->children.GetEnDelete(N)) {
        Except("DeleteThisFromParent[Parent->children.GetEnDelete(N)]");
      }
      Parent->DeleteChild(N);
    }
  }
  //
  virtual int CalcNumLevel();
  bool ThisIsParent(TComponent *Child);
  //
  TComponent *SearchThisOrParent(const svl::TType &TypeParent);
  TComponent *SearchParent      (const svl::TType &TypeParent);
  
protected:  
  virtual void TComponent_BeforeDeleteChildren() {}
  virtual void TComponent_AfterAddChild(TComponent *Child) {}
  //
  virtual void TComponent_AddToParent     (TComponent *Parent) {}
  virtual void TComponent_DeleteFromParent(TComponent *Parent) {}

  // Unlink /////////////////////////
  private:   void beforeUnlinkThis();
  protected: virtual void TComponent_BeforeUnlinkThis() {}
  protected: virtual void TComponent_AfterUnlinkChildren() {}
  
private:
  svl::TArray children;
  TComponent *parent;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TComponentArray
{
  void Clear() { a.Clear();}
  int  Count() { return a.Numb();}
  //
  void Add(TComponent *C,bool EnDelete) { a.Add(C,EnDelete);}
  //
  TComponent &operator[](int N) { return *(TComponent*)a.Get(N);}
  TComponent &Get(int N)        { return *(TComponent*)a.Get(N);}
  //
  void Delete(TComponent *C) { a.Delete(C);}
  void Delete(int         N) { a.Delete(N);}
  //
  bool DeleteIfSearch(TComponent *C) { return a.DeleteIfSearch(C);}
  //
  bool Search(TComponent *C)            { return a.Search(C);}
  bool Search(TComponent *C,int &OutNC) { return a.Search(C,OutNC);}

private:
  svl::TArray a;
};

///////////////////////////////////////////////////////////////////////////////

struct TGeometryRect
{
  grf::TRect RParent;
  grf::TRect RParentVisible;
  grf::TRect RThis;
  grf::TRect RThisVisible;
  grf::TRect RThisClient;
  grf::TRect RThisClientVisible;
  //
  TGeometryRect() {}
  TGeometryRect(const TGeometryRect &V) { *this = V;}
  //
  void CopyFrom(const TGeometryRect &V);
  void operator = (const TGeometryRect &V) { CopyFrom(V); }
};

///////////////////////////////////////////////////////////////////////////////
struct TPaint;
///////////////////////////////////////////////////////////////////////////////

struct TPaintStack
{
  struct TItem
  {
    TComponent *Component;
    TPaint     *Paint;
  };
  //
  TPaintStack();
 ~TPaintStack();
  //
  void Push(TComponent &Component,TPaint &Paint);
  void Pop () { if (count) { count--;} }
  //
  int Count() { return count;}
  TItem &Get(int N);
  TItem &operator[](int N) { return Get(N); }

private:
  svl_Except;
  TItem array[200];
  int   count;
};

///////////////////////////////////////////////////////////////////////////////

struct TPaint
{
  enum EState { EState_PaintAll,EState_PaintUpdate};
  //
  EState        State;
  grf::TDC      DC;
  grf::TRect    RClientPaint;
  TGeometryRect GRect;
  TPaintStack  *PaintStack;
  //grf::TRegion *ClipRegion;
  //
  TPaint() { PaintStack = NULL; /*ClipRegion = NULL;*/ }
  TPaint(const TPaint &V) { *this = V;}
  //
  void CopyFrom(const TPaint &V);
  void operator = (const TPaint &V) { CopyFrom(V); }
};

///////////////////////////////////////////////////////////////////////////////

struct TBorder : public svl::TPointer //: public TDebug
{
  int Left,Top,Right,Bottom;
  //
  TBorder() { Left = Top = Right = Bottom = 0; isNull = true;}
  TBorder(const TBorder &V) { *this = V;} 
  //
  bool IsNull()  { return isNull;}
  void SetNull() { isNull = true;}
  //
  void Set(int left,int top,int right,int bottom) { Left = left; Top = top; Right = right; Bottom = bottom; isNull = false;}
  //
  void SetFromParent(TBorder &P) { if (isNull) { Left = P.Left; Top = P.Top; Right = P.Right; Bottom = P.Bottom; isNull = P.isNull;} }
  //TBorder &operator = (const TBorder &V) { Left = V.Left; Top = V.Top; Right = V.Right; Bottom = V.Bottom; isNull = V.isNull; return *this;}

  //
  svl::TInfoParam AddInfoTo(svl::TInfoParam Info);

private:
  bool isNull;
};

///////////////////////////////////////////////////////////////////////////////
}

#endif
